// Copyright (C) 2012 by Johann Duscher <jonny.dee@gmx.net>
// 
// This file is part of barcodeart-pp.
//
// barcodeart-pp is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// barcodeart-pp is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with barcodeart-pp. If not, see <http://www.gnu.org/licenses/>.

#include "Encoder.hpp"
#include "QRCode.hpp"

#include "import_libqrencode.hpp"


namespace barcodeart
{

namespace qrcode
{

namespace qrencode
{

Encoder::Encoder()
{
}

Encoder::~Encoder()
{
}

clib::QRencodeMode clibEncodeMode(qrcode::Encoding::Type value)
{
    switch (value)
    {
    case qrcode::Encoding::NUMERIC:
        return clib::QR_MODE_NUM;
    case qrcode::Encoding::ALPHANUMERIC:
        return clib::QR_MODE_AN;
    case qrcode::Encoding::BINARY:
        return clib::QR_MODE_8;
    case qrcode::Encoding::KANJI:
        return clib::QR_MODE_KANJI;
    default:
        break;
    }

    return clib::QR_MODE_NUL;
}

clib::QRecLevel clibECLevel(qrcode::ErrorCorrection::Level value)
{
    switch (value)
    {
    case qrcode::ErrorCorrection::LOW:
        return clib::QR_ECLEVEL_L;
    case qrcode::ErrorCorrection::MEDIUM:
        return clib::QR_ECLEVEL_M;
    case qrcode::ErrorCorrection::QUALITY:
        return clib::QR_ECLEVEL_Q;
    case qrcode::ErrorCorrection::HIGH:
        return clib::QR_ECLEVEL_H;
    }
    // Should not never be reached.
    return clib::QR_ECLEVEL_L;
}

IBarCode::ConstPtr Encoder::encode(const uint8_t* pData, size_t size, const IEncoderConfig& qrCodeConfig) const
{
    const qrcode::EncoderConfig& config = dynamic_cast<const qrcode::EncoderConfig&>(qrCodeConfig);

    IBarCode* pBarCode = 0;

    switch (config.getEncodingType())
    {
    case Encoding::BINARY:
        {
            pBarCode = new QRCode(clib::QRcode_encodeData(
                                  (int)size,
                                  pData,
                                  config.getVersion(),
                                  clibECLevel(config.getErrorCorrectionLevel())));
            break;
        }
    case Encoding::ALPHANUMERIC:
    case Encoding::KANJI:
    case Encoding::NUMERIC:
        {
            pBarCode = new QRCode(clib::QRcode_encodeString(
                                  reinterpret_cast<const char*>(pData),
                                  config.getVersion(),
                                  clibECLevel(config.getErrorCorrectionLevel()),
                                  clibEncodeMode(config.getEncodingType()),
                                  config.isCaseSensitive()));
            break;
        }
    default:
        break;
    }

    return IBarCode::ConstPtr(pBarCode);
}

}

}

}
